package typistcal.executor;

import java.util.Vector;

import typistcal.commandlogic.Command;
import typistcal.commandlogic.Event;
import typistcal.commandlogic.TimeUtility;
import typistcal.storage.FileOperator;
import typistcal.userinterface.UserInterface;

import java.util.logging.Level;
import java.util.logging.Logger;

//@author A0105493H

public class Executor {
	private static int CAPACITY = 100;
	private static int executionStatus = 1;
	private static final Logger LOGGER = Logger.getLogger(Executor.class
			.getName());
	private static Vector<Integer> sList, dList, tList;
	private static FileOperator scheduledFile = new FileOperator(
			"scheduledFile.txt");

	private static FileOperator deadlineFile = new FileOperator(
			"deadlineFile.txt");
	private static FileOperator todoFile = new FileOperator("todoFile.txt");
	private static StringBuffer feedback = new StringBuffer(CAPACITY);
	private static boolean isMultiple = true;
	private static int MAXSIZE = 100;
	private static String[] lineContent = new String[MAXSIZE];
	private static String[] replacementContent = new String[MAXSIZE];
	private static String[] partialContent;

	public static StringBuffer executeCommand(Command userCommand) {

		switch (userCommand.commandType) {
		case ADD_INFO:
			addEvent(userCommand.event);
			System.out.print("\n"
					+ "start:"
					+ convertToStandard(
							"test2 by 12 April 2014 8:00 Incomplete",
							"deadline") + "end!");
			break;
		case DELETE_INFO:
			deleteEvent(userCommand.event.eventKeyword,
					userCommand.event.lineNumber);
			break;
		case SHOW_INFO:
			showEvent(userCommand.event.eventKeyword);
			break;
		case UPDATE_INFO:
			updateEvent(userCommand);

			break;
		case FIND_INFO:

			findEvent(userCommand.event.eventKeyword);
			break;
		case ADD_FOR_UNDO:

			addForUndo_Redo(userCommand.eventRecordAndFiles, false);
			break;
		case DELETE_FOR_UNDO:
			deleteForUndo_Redo(userCommand.eventRecordAndFiles);
			break;
		case UPDATE_FOR_UNDO:
			updateForUndo_Redo(userCommand.eventRecordAndFiles);
			break;
		case ADD_FOR_REDO:
			addForUndo_Redo(userCommand.eventRecordAndFiles, false);
			break;
		case DELETE_FOR_REDO:
			deleteForUndo_Redo(userCommand.eventRecordAndFiles);
			break;
		case UPDATE_FOR_REDO:
			updateForUndo_Redo(userCommand.eventRecordAndFiles);
			break;
		default:
			UserInterface
			.displayToDisplayArea("Only CRUD functions are available right now");
		}

		return feedback;
	}

	private static void updateForUndo_Redo(String eventRecordAndFiles) {
		String[] temp = eventRecordAndFiles.split("yxmqa");

		deleteForUndo_Redo(temp[0]);
		addForUndo_Redo(temp[1].trim(), true);
		String replacement = feedback.toString().split("successfully added")[1];
		String original = removeLineNumber(temp[0]);

		feedback = new StringBuffer(executionStatus + "successfully "
				+ replacement + " yxmqa " + original);

	}

	private static void deleteForUndo_Redo(String wholeLine) {
		Vector<Integer> sList1 = scheduledFile.listOfTheFile();
		Vector<Integer> dList1 = deadlineFile.listOfTheFile();
		Vector<Integer> tList1 = todoFile.listOfTheFile();
		String[] eachLine = new String[CAPACITY];
		eachLine = findEachLineForAdd(wholeLine);

		StringBuilder sb = new StringBuilder();
		sb = findIndexForMultipleDeletion(eachLine, sList1.size(),
				dList1.size());
		StringBuffer deleteString = deleteMultiple(sb.toString(), sList1,
				dList1, tList1);
		if (isMultiple) {
			feedback = new StringBuffer(executionStatus
					+ "are successfully deleted" + deleteString.toString());
		} else {
			feedback = new StringBuffer(executionStatus
					+ "is successfully deleted" + deleteString.toString());
		}
	}

	private static void findEvent(String eventKeyword) {
		showEvent(eventKeyword);
	}

	private static void addForUndo_Redo(String wholeLine, boolean isUpdate) {
		StringBuffer fb = new StringBuffer();
		if (Utility.isMultipleLines(wholeLine)) {

			UserInterface.displayToDisplayArea("The following tasks");

			String[] eachLine = new String[CAPACITY];
			eachLine = findEachLineForAdd(wholeLine);
			int number = Integer.parseInt(eachLine[0]);

			for (int i = 1; i <= number; i++) {
				int lineNumber = undo_redo_Add_eachLine(eachLine[i]);
				fb.append(lineNumber + " " + eachLine[i] + "\n");
			}
			feedback = new StringBuffer(executionStatus
					+ "are successfully added " + fb.toString());
		} else {
			if (!isUpdate) {
				UserInterface.displayToDisplayArea("The following task");
			} else {
				UserInterface.displayToDisplayArea("is updated to");
			}
			int lineNumber = undo_redo_Add_eachLine(wholeLine);
			feedback = new StringBuffer(executionStatus
					+ "is successfully added " + lineNumber + " " + wholeLine);
		}
	}

	private static int undo_redo_Add_eachLine(String wholeLine) {
		FileOperator currentFile = findFile(wholeLine, scheduledFile, todoFile,
				deadlineFile);

		String content = extractContent(wholeLine);
		String type = findType(wholeLine);
		currentFile.insertIntoFile(content,
				currentFile.getNumberOfLinesInFile());
		UserInterface.displayToDisplayArea(convertToStandard(content, type));
		return currentFile.getNumberOfLinesInFile();
	}

	private static void deleteEvent(String originalKeyword, int[] lineNumber) {

		if (lineNumber[0] != -1) {
			String stringLineNumber = Utility
					.convertIntArrayToString(lineNumber);
			StringBuffer tempString = deleteMultiple(stringLineNumber, sList,
					dList, tList);
			feedback = new StringBuffer(executionStatus
					+ "is successfully deleted" + tempString.toString());

			return;
		}

		StringBuffer deleteString = new StringBuffer();
		Vector<Integer> scheduledList = findListOfNumbers(scheduledFile,
				originalKeyword);
		Vector<Integer> deadlineList = findListOfNumbers(deadlineFile,
				originalKeyword);
		Vector<Integer> todoList = findListOfNumbers(todoFile, originalKeyword);

		int totalNumber = scheduledList.size() + deadlineList.size()
				+ todoList.size();

		if (totalNumber == 0) {
			executionStatus = 0;
			feedback = new StringBuffer(executionStatus + "Keyword \""
					+ originalKeyword + "\" is not found");
			executionStatus = 1;
		} else if (totalNumber == 1) {
			UserInterface.displayToDisplayArea("The following task");
			if (scheduledList.size() == 1) {

				feedback = new StringBuffer(executionStatus
						+ "is successfully deleted "
						+ scheduledFile.getLineContent(scheduledList.get(0))
						+ " scheduledFile.txt");
				UserInterface.displayToDisplayArea(convertToStandard(
						scheduledFile.getLineContent(scheduledList.get(0)),
						"schedule"));
				scheduledFile.deleteFromFile(scheduledList.get(0).intValue());
			} else if (deadlineList.size() == 1) {

				feedback = new StringBuffer(executionStatus
						+ "is successfully deleted "
						+ deadlineFile.getLineContent(deadlineList.get(0))
						+ " deadlineFile.txt");
				UserInterface.displayToDisplayArea(convertToStandard(
						deadlineFile.getLineContent(deadlineList.get(0)),
						"deadline"));
				deadlineFile.deleteFromFile(deadlineList.get(0).intValue());
			} else if (todoList.size() == 1) {
				feedback = new StringBuffer(executionStatus
						+ "is successfully deleted "
						+ todoFile.getLineContent(todoList.get(0))
						+ " todoFile.txt");
				UserInterface.displayToDisplayArea(convertToStandard(
						todoFile.getLineContent(todoList.get(0)), "todo"));
				todoFile.deleteFromFile(todoList.get(0).intValue());
			}
		} else {
			StringBuilder sb = new StringBuilder(
					"Which one do you want to delete?\n");
			String[][] output = new String[scheduledList.size()
			                               + deadlineList.size() + todoList.size()][3];

			output = appendEventList(scheduledList, output, scheduledFile, 1,
					"schedule");
			output = appendEventList(deadlineList, output, deadlineFile,
					scheduledList.size() + 1, "deadline");
			output = appendEventList(todoList, output, todoFile,
					scheduledList.size() + deadlineList.size() + 1, "todo");

			UserInterface.displayInTable(output);
			String deleteIndex = UserInterface.displayAndAskForFeedback(sb
					.toString());
			deleteString = deleteMultiple(deleteIndex, scheduledList,
					deadlineList, todoList);
			while (deleteString.length() == 0) {
				deleteIndex = UserInterface
						.displayAndAskForFeedback("please enter valid number");
				deleteString = deleteMultiple(deleteIndex, scheduledList,
						deadlineList, todoList);
			}
			if (isMultiple) {
				feedback = new StringBuffer(executionStatus
						+ "are successfully deleted" + deleteString.toString());
			} else {
				feedback = new StringBuffer(executionStatus
						+ "is successfully deleted" + deleteString.toString());
			}

		}

	}

	private static <T> StringBuffer deleteMultiple(String i,
			Vector<Integer> scheduledList, Vector<Integer> deadlineList,
			Vector<Integer> todoList) {
		StringBuffer deleteString = new StringBuffer();
		int scheduleDeleteTimes = 0;
		int deadlineDeleteTimes = 0;
		int todoDeleteTimes = 0;

		Integer lengthOftodo = new Integer(todoList.size()
				+ deadlineList.size() + scheduledList.size()
				+ scheduleDeleteTimes + deadlineDeleteTimes + todoDeleteTimes);

		String indices[] = i.split(" ");

		if (indices.length == 1) {
			isMultiple = false;
		}
		for (String eachIndex : indices) { // check each one must be an integer

			if (!isInteger(eachIndex)) {

				UserInterface
				.displayToDisplayArea("Please input valid index number");
				executionStatus = 0;
				feedback = new StringBuffer(executionStatus + "Index number "
						+ eachIndex + " is invalid");
				executionStatus = 1;

				return deleteString;
			} else {
				Integer eachIndexInteger = Integer.parseInt(eachIndex);
				if (eachIndexInteger.compareTo(lengthOftodo) > 0) {

					UserInterface
					.displayToDisplayArea("Please input valid index number");
					executionStatus = 0;
					feedback = new StringBuffer(executionStatus
							+ "Index number " + eachIndex + " is invalid");
					executionStatus = 1;

					return deleteString;
				}
			}
		}
		if (isMultiple) {
			UserInterface.displayToDisplayArea("The following tasks");
		} else {
			UserInterface.displayToDisplayArea("The following task");
		}
		for (String eachIndex : indices) { // all the input are integers
			Integer indexNumber = Integer.parseInt(eachIndex);
			indexNumber = new Integer(indexNumber.intValue() - 1);

			int indexNo = indexNumber.intValue();
			if (indexNo < scheduledList.size()) {
				UserInterface.displayToDisplayArea(convertToStandard(
						scheduledFile
						.getLineContent(new Integer(scheduledList.get(
								indexNo).intValue()
								- scheduleDeleteTimes)), "schedule"));
				deleteString.append(scheduledFile.getLineContent(new Integer(
						scheduledList.get(indexNo).intValue()
						- scheduleDeleteTimes))
						+ " scheduledFile.txt\n");
				scheduledFile.deleteFromFile(scheduledList.get(indexNo)
						.intValue() - scheduleDeleteTimes);
				scheduleDeleteTimes++;

			} else if (indexNo < (scheduledList.size() + deadlineList.size())) {
				UserInterface.displayToDisplayArea(convertToStandard(
						deadlineFile.getLineContent(new Integer(deadlineList
								.get(indexNo - scheduledList.size()).intValue()
								- deadlineDeleteTimes)), "deadline"));
				deleteString.append(deadlineFile.getLineContent(new Integer(
						deadlineList.get(indexNo - scheduledList.size())
						.intValue() - deadlineDeleteTimes))
						+ " deadlineFile.txt\n");

				deadlineFile.deleteFromFile(deadlineList.get(
						indexNo - scheduledList.size()).intValue()
						- deadlineDeleteTimes);
				deadlineDeleteTimes++;
			} else {

				String temp = todoFile.getLineContent(new Integer(todoList.get(
						indexNo - scheduledList.size() - deadlineList.size())
						.intValue()
						- todoDeleteTimes));
				UserInterface.displayToDisplayArea(convertToStandard(temp,
						"todo"));
				deleteString.append(todoFile.getLineContent(new Integer(
						todoList.get(
								indexNo - scheduledList.size()
								- deadlineList.size()).intValue()
								- todoDeleteTimes))
								+ " todoFile.txt\n");
				todoFile.deleteFromFile(todoList.get(
						indexNo - scheduledList.size() - deadlineList.size())
						.intValue()
						- todoDeleteTimes);
				todoDeleteTimes++;
			}

		}
		return deleteString;
	}

	private static boolean isInteger(String input) {
		try {
			Integer.parseInt(input);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	private static void showEvent(String originalKeyword) {
		int numberOfLines = 0;

		if (originalKeyword.trim().isEmpty()) {

			numberOfLines = scheduledFile.getNumberOfLinesInFile()
					+ todoFile.getNumberOfLinesInFile()
					+ deadlineFile.getNumberOfLinesInFile();

			Vector<Integer> scheduledList = scheduledFile.listOfTheFile();
			Vector<Integer> deadlineList = deadlineFile.listOfTheFile();
			Vector<Integer> todoList = todoFile.listOfTheFile();
			sList = scheduledList;
			dList = deadlineList;
			tList = todoList;
			String[][] output = new String[scheduledList.size()
			                               + deadlineList.size() + todoList.size()][3];

			output = appendEventList(scheduledList, output, scheduledFile, 1,
					"schedule");
			output = appendEventList(deadlineList, output, deadlineFile,
					scheduledList.size() + 1, "deadline");
			output = appendEventList(todoList, output, todoFile,
					scheduledList.size() + deadlineList.size() + 1, "todo");
			UserInterface.displayInTable(output);
			feedback = new StringBuffer(executionStatus + "" + numberOfLines
					+ " task(s) found");
			return;
		}

		if (originalKeyword.equalsIgnoreCase("completed")) {
			showEvent(" complete");
			return;
		}
		if (TimeUtility.isDate(originalKeyword)) { // it is a date w/o time

			findDuration(scheduledFile, originalKeyword, "schedule");

		}
		Vector<Integer> scheduledList = findListOfNumbers(scheduledFile,
				originalKeyword);
		Vector<Integer> deadlineList = findListOfNumbers(deadlineFile,
				originalKeyword);
		Vector<Integer> todoList = findListOfNumbers(todoFile, originalKeyword);
		sList = scheduledList;
		dList = deadlineList;
		tList = todoList;
		String[][] output = new String[scheduledList.size()
		                               + deadlineList.size() + todoList.size()][3];

		output = appendEventList(scheduledList, output, scheduledFile, 1,
				"schedule");
		output = appendEventList(deadlineList, output, deadlineFile,
				scheduledList.size() + 1, "deadline");
		output = appendEventList(todoList, output, todoFile,
				scheduledList.size() + deadlineList.size() + 1, "todo");

		UserInterface.displayInTable(output);

		numberOfLines = scheduledList.size() + deadlineList.size()
				+ todoList.size();
		if (originalKeyword.equalsIgnoreCase(" complete")) {
			feedback = new StringBuffer(executionStatus + "There are "
					+ numberOfLines + " completed tasks found");
		} else {
			feedback = new StringBuffer(executionStatus + "" + numberOfLines
					+ " task(s) found relevant to \"" + originalKeyword + "\""
					+ '.');
		}

	}

	private static Vector<Integer> findListOfNumbers(FileOperator file,
			String keyword) {
		Vector<Integer> listOfNumbers = new Vector<Integer>();
		listOfNumbers = file.findEntriesOfKeyword(keyword);
		return listOfNumbers;
	}

	private static void updateEvent(Command userCommand) {
		String originalKeyword = userCommand.event.eventKeyword;
		String replacementKeyword = userCommand.event.toKeyword;
		String fieldKeyword = userCommand.event.fieldKeyword;
		Event event = userCommand.event;
		int[] lineNumber = userCommand.event.lineNumber;
		Vector<Integer> scheduledList = findListOfNumbers(scheduledFile,
				originalKeyword);
		Vector<Integer> deadlineList = findListOfNumbers(deadlineFile,
				originalKeyword);
		Vector<Integer> todoList = findListOfNumbers(todoFile, originalKeyword);
		String replacement;
		StringBuffer updateString = new StringBuffer();
		String lineContent = new String();
		int totalNumber = scheduledList.size() + deadlineList.size()
				+ todoList.size();
		if (lineNumber[0] != -1) {
			updateString = updateInFile(new Integer(lineNumber[0]).toString(),
					sList, dList, tList, replacementKeyword, originalKeyword,
					fieldKeyword, event);
			while (updateString.length() == 0) {
				String lineNo = UserInterface
						.displayAndAskForFeedback("Please enter valid number");
				updateString = updateInFile(lineNo, scheduledList,
						deadlineList, todoList, replacementKeyword,
						originalKeyword, fieldKeyword, event);
			}
			feedback = new StringBuffer(executionStatus + "successfully "
					+ updateString.toString());
			return;
		}
		if (totalNumber == 0) {
			executionStatus = 0;
			feedback = new StringBuffer(executionStatus + "Keyword \""
					+ originalKeyword + "\" not found");
			executionStatus = 1;
		} else if (totalNumber == 1) {

			if (scheduledList.size() == 1) {
				lineContent = scheduledFile
						.getLineContent(scheduledList.get(0));
				replacement = replaceInSchedule(lineContent,
						replacementKeyword, fieldKeyword, event);
				if (replacement == null) {
					UserInterface
					.displayToDisplayArea("Status has been updated to completed already");
					feedback = new StringBuffer(executionStatus);
					return;
				}
				UserInterface.displayToDisplayArea("The following task");
				UserInterface.displayToDisplayArea("Original content:    "
						+ convertToStandard(lineContent, "schedule")
						+ "\nis updated to:    "
						+ convertToStandard(replacement, "schedule"));
				int temp = scheduledList.get(0).intValue();
				Integer t = new Integer(temp + 1);
				feedback = new StringBuffer(executionStatus + "successfully "
						+ t + " " + replacement + " scheduledFile.txt "
						+ "yxmqa " + lineContent + " scheduledFile.txt ");
				scheduledFile.deleteFromFile(scheduledList.get(0).intValue());
				scheduledFile.insertIntoFile(replacement, scheduledList.get(0)
						.intValue());

			} else if (deadlineList.size() == 1) {
				lineContent = deadlineFile.getLineContent(deadlineList.get(0));
				replacement = replaceInDeadline(lineContent,
						replacementKeyword, fieldKeyword, event);
				if (replacement == null) {
					UserInterface
					.displayToDisplayArea("Status has been updated to completed already");
					feedback = new StringBuffer(executionStatus);
					return;
				}
				UserInterface.displayToDisplayArea("The following task");
				UserInterface.displayToDisplayArea("Original content:    "
						+ convertToStandard(lineContent, "deadline")
						+ "\nis udpated to:    "
						+ convertToStandard(replacement, "deadline"));
				int temp = deadlineList.get(0).intValue();
				Integer t = new Integer(temp + 1);
				feedback = new StringBuffer(executionStatus + "successfully "
						+ t + " " + replacement + " deadlineFile.txt "
						+ "yxmqa " + lineContent + " deadlineFile.txt ");
				deadlineFile.deleteFromFile(deadlineList.get(0).intValue());
				deadlineFile.insertIntoFile(replacement, deadlineList.get(0)
						.intValue());

			} else if (todoList.size() == 1) {
				lineContent = todoFile.getLineContent(todoList.get(0));
				replacement = replaceInTodo(lineContent, replacementKeyword,
						fieldKeyword, event);
				if (replacement == null) {
					UserInterface
					.displayToDisplayArea("Status has been updated to completed already");
					return;
				}
				UserInterface.displayToDisplayArea("The following task");
				UserInterface.displayToDisplayArea("Original content:    "
						+ convertToStandard(lineContent, "todo")
						+ "\nis updated to:    "
						+ convertToStandard(replacement, "todo"));
				int temp = todoList.get(0).intValue();
				Integer t = new Integer(temp + 1);
				feedback = new StringBuffer(executionStatus + "successfully "
						+ t + " " + replacement + " todoFile.txt yxmqa "
						+ lineContent + " todoFile.txt ");
				todoFile.deleteFromFile(todoList.get(0).intValue());
				todoFile.insertIntoFile(replacement, todoList.get(0).intValue());
			}
		} else {

			StringBuilder sb = new StringBuilder(
					"Which one do you want to update?\n");
			String[][] output = new String[scheduledList.size()
			                               + deadlineList.size() + todoList.size()][3];

			output = appendEventList(scheduledList, output, scheduledFile, 1,
					"schedule");
			output = appendEventList(deadlineList, output, deadlineFile,
					scheduledList.size() + 1, "deadline");
			output = appendEventList(todoList, output, todoFile,
					scheduledList.size() + deadlineList.size() + 1, "todo");

			UserInterface.displayInTable(output);

			String updateIndex = UserInterface.displayAndAskForFeedback(sb
					.toString());
			updateString = updateInFile(updateIndex, scheduledList,
					deadlineList, todoList, replacementKeyword,
					originalKeyword, fieldKeyword, event);
			while (updateString.length() == 0) {
				updateIndex = UserInterface
						.displayAndAskForFeedback("Please enter valid number");
				updateString = updateInFile(updateIndex, scheduledList,
						deadlineList, todoList, replacementKeyword,
						originalKeyword, fieldKeyword, event);
			}
			feedback = new StringBuffer(executionStatus + "successfully "
					+ updateString.toString());
		}

	}

	private static <T> StringBuffer updateInFile(String updateIndex,
			Vector<Integer> scheduledList, Vector<Integer> deadlineList,
			Vector<Integer> todoList, String replacementString,
			String originalString, String fieldKeyword, Event event) {
		StringBuffer updateString = new StringBuffer();

		Integer lengthOfSchedule = new Integer(scheduledList.size());
		Integer lengthOfdeadline = new Integer(deadlineList.size()
				+ scheduledList.size());
		Integer lengthOftodo = new Integer(todoList.size()
				+ deadlineList.size() + scheduledList.size());

		if (!isInteger(updateIndex)) {
			return updateString;
		} else {
			Integer eachIndexInteger = Integer.parseInt(updateIndex);
			if (eachIndexInteger.compareTo(lengthOftodo) > 0) {
				return updateString;
			}
		}

		Integer indexNumber = Integer.parseInt(updateIndex);
		indexNumber = new Integer(indexNumber.intValue() - 1);
		String lineContent = new String();
		String replace = new String();
		int indexNo = indexNumber.intValue();
		if (indexNumber.compareTo(lengthOfSchedule) < 0) {
			lineContent = scheduledFile.getLineContent(new Integer(indexNo));
			replace = replaceInSchedule(lineContent, replacementString,
					fieldKeyword, event);
			if (replace == null) {
				UserInterface
				.displayToDisplayArea("Status has been updated to completed already");

				return updateString;
			}
			UserInterface.displayToDisplayArea("The following task");
			UserInterface.displayToDisplayArea("Original content:    "
					+ convertToStandard(lineContent, "schedule")
					+ "\nis updated to:    "
					+ convertToStandard(replace, "schedule"));

			updateString.append((scheduledList.get(indexNo).intValue() + 1)
					+ " " + replace + " scheduledFile.txt yxmqa " + lineContent
					+ " scheduledFile.txt ");
			scheduledFile.deleteFromFile(scheduledList.get(indexNo).intValue());
			scheduledFile.insertIntoFile(replace, scheduledList.get(indexNo)
					.intValue());

		} else if (indexNumber.compareTo(lengthOfdeadline) < 0) {

			lineContent = deadlineFile.getLineContent(new Integer(indexNo
					- scheduledList.size()));
			replace = replaceInDeadline(lineContent, replacementString,
					fieldKeyword, event);
			if (replace == null) {

				UserInterface
				.displayToDisplayArea("Status has been updated to completed already");
				return updateString;
			}
			UserInterface.displayToDisplayArea("The following task");
			UserInterface.displayToDisplayArea("Original content:    "
					+ convertToStandard(lineContent, "deadline")
					+ "\nis updated to:    "
					+ convertToStandard(replace, "deadline"));
			updateString.append((deadlineList.get(
					indexNo - scheduledList.size()).intValue() + 1)
					+ " "
					+ replace
					+ " deadlineFile.txt yxmqa "
					+ lineContent
					+ " deadlineFile.txt ");
			deadlineFile.deleteFromFile(deadlineList.get(
					indexNo - scheduledList.size()).intValue());
			deadlineFile
			.insertIntoFile(replace,
					deadlineList.get(indexNo - scheduledList.size())
					.intValue());

		} else {
			lineContent = todoFile.getLineContent(new Integer(indexNo
					- scheduledList.size() - deadlineList.size()));
			replace = replaceInTodo(lineContent, replacementString,
					fieldKeyword, event);
			if (replace == null) {

				UserInterface
				.displayToDisplayArea("Status has been updated to completed already");
				return updateString;
			}
			UserInterface.displayToDisplayArea("The following task");
			UserInterface.displayToDisplayArea("Original content:    "
					+ convertToStandard(lineContent, "todo")
					+ "\nis updated to:    "
					+ convertToStandard(replace, "todo"));
			updateString.append((todoList.get(
					indexNo - scheduledList.size() - deadlineList.size())
					.intValue() + 1)
					+ " "
					+ replace
					+ " todoFile.txt yxmqa "
					+ lineContent
					+ " todoFile.txt ");
			todoFile.deleteFromFile(todoList.get(
					indexNo - scheduledList.size() - deadlineList.size())
					.intValue());
			todoFile.insertIntoFile(
					replace,
					todoList.get(
							indexNo - scheduledList.size()
							- deadlineList.size()).intValue());

		}

		return updateString;
	}

	private static void addEvent(Event event) {

		switch (event.eventType) {

		case SCHEDULED:
			if (isDuplicated(event, scheduledFile)) {
				return;
			} else {
				insertIntoFile(event.toString(),
						scheduledFile.getNumberOfLinesInFile(), scheduledFile);
				UserInterface.displayToDisplayArea("    "
						+ convertToStandard(event.toString(), "schedule"));
			}
			feedback = new StringBuffer(executionStatus
					+ "is successfully added "
					+ scheduledFile.getNumberOfLinesInFile() + " "
					+ event.toString() + " scheduledFile.txt ");
			break;
		case DEADLINE:
			if (isDuplicated(event, deadlineFile)) {
				return;
			} else {
				insertIntoFile(event.toString(),
						deadlineFile.getNumberOfLinesInFile(), deadlineFile);
				UserInterface.displayToDisplayArea("    "
						+ convertToStandard(event.toString(), "deadline"));
			}
			feedback = new StringBuffer(executionStatus
					+ "is successfully added "
					+ deadlineFile.getNumberOfLinesInFile() + " "
					+ event.toString() + " deadlineFile.txt ");
			break;
		case TODO:
			if (isDuplicated(event, todoFile)) {
				return;
			} else {
				insertIntoFile(event.toString(),
						todoFile.getNumberOfLinesInFile(), todoFile);
				UserInterface.displayToDisplayArea("    "
						+ convertToStandard(event.toString(), "todo"));

			}
			feedback = new StringBuffer(executionStatus
					+ "is successfully added "
					+ todoFile.getNumberOfLinesInFile() + " "
					+ event.toString() + " todoFile.txt ");
			break;

		default:
			LOGGER.log(Level.SEVERE, "Wrong type keyword of event!");
		}

	}

	private static void insertIntoFile(String eventString, int lineNo,
			FileOperator file) {
		UserInterface.displayToDisplayArea("The following task");
		file.insertIntoFile(eventString, lineNo);
	}

	private static boolean isDuplicated(Event event, FileOperator file) {
		Vector<Integer> listOfNumbers = file.findEntriesOfKeyword(event.label);
		for (Integer sequenceNo : listOfNumbers) {

			if (event.toString().equals(file.getLineContent(sequenceNo))) {
				executionStatus = 0;
				feedback = new StringBuffer(executionStatus
						+ "The task already exists");
				executionStatus = 1;
				return true;
			}
		}
		return false;
	}

	private static FileOperator findFile(String wholeLine,
			FileOperator scheduledFile, FileOperator todoFile,
			FileOperator deadlineFile) {
		String[] parts = wholeLine.split(" ");
		try {
			if (parts[parts.length - 1].contains("todo")) {
				return todoFile;
			} else if (parts[parts.length - 1].contains("deadline")) {
				return deadlineFile;
			} else {
				return scheduledFile;
			}
		} catch (IndexOutOfBoundsException e) {
			LOGGER.log(Level.SEVERE, "The format of event is wrong!");
		}
		return null;
	}

	private static String extractContent(String wholeLine) {
		String[] parts = wholeLine.split(" ");
		String content = new String();
		for (int i = 0; i < parts.length - 2; i++) {
			content = content + parts[i] + " ";
		}
		content = content + parts[parts.length - 2];
		return content;
	}

	public static int findLineNumber(String wholeLine) {
		String[] parts = wholeLine.split(" ");
		return Integer.parseInt(parts[0]);
	}

	private static String removeLineNumber(String wholeLine) {
		String[] parts = wholeLine.split(" ");
		String content = new String();
		for (int i = 1; i < parts.length - 1; i++) {
			content = content + parts[i] + " ";
		}
		content = content + parts[parts.length - 1];
		return content;
	}

	static String findType(String wholeLine) {

		if (wholeLine.contains("scheduledFile.txt")) {
			return "schedule";
		} else if (wholeLine.contains("deadlineFile.txt")) {
			return "deadline";
		} else {
			return "todo";
		}
	}

	private static String[] findEachLineForAdd(String wholeLine) {
		String[] eachLine = new String[MAXSIZE];
		String[] each = wholeLine.split("\n");
		eachLine[0] = (new Integer(each.length)).toString();
		for (int i = 0; i < each.length; i++) {
			eachLine[i + 1] = each[i];

		}
		return eachLine;
	}

	private static Vector<Integer> findDuration(FileOperator file,
			String originalKeyword, String type) {
		Vector<Integer> list = new Vector<Integer>();
		int size = file.getNumberOfLinesInFile();
		for (int i = 0; i < size; i++) {
			String content = file.getLineContent(new Integer(i));
			String endDate = findEndDate(content);
			String endTime = findEndTime(content);
			String startDate = findStartDate(content);
			String startTime = findStartTime(content);
			if (TimeUtility.isValidSchedule(startDate, startTime,
					originalKeyword, "23:59")
					&& TimeUtility.isValidSchedule(originalKeyword, "00:00",
							endDate, endTime)) {
				list.add(new Integer(i));
			}

		}
		return list;
	}

	private static String findStartTime(String content) {
		int fromIndex = content.lastIndexOf("from ");
		String temp = content.substring(fromIndex);
		partialContent = temp.split(" ");
		return partialContent[4];
	}

	private static String findStartDate(String content) {
		int fromIndex = content.lastIndexOf("from ");
		String temp = content.substring(fromIndex);
		partialContent = temp.split(" ");
		return partialContent[1] + " " + partialContent[2] + " "
		+ partialContent[3];
	}

	private static String findEndTime(String content) {
		int toIndex = content.lastIndexOf("to ");
		String temp = content.substring(toIndex);
		partialContent = temp.split(" ");
		return partialContent[4];
	}

	private static String findEndDate(String content) {
		int toIndex = content.lastIndexOf("to ");
		String temp = content.substring(toIndex);
		partialContent = temp.split(" ");
		return partialContent[1] + " " + partialContent[2] + " "
		+ partialContent[3];
	}

	static String[] increaseTimes(String findType, int scheduleDeleteTimes,
			int deadlineDeleteTimes, int todoDeleteTimes) {
		String[] temp = new String[2];
		switch (findType) {
		case ("schedule"): {
			scheduleDeleteTimes++;
			temp[1] = new Integer(scheduleDeleteTimes).toString();
			temp[0] = "schedule";
		}
		case ("deadline"): {
			deadlineDeleteTimes++;
			temp[1] = new Integer(deadlineDeleteTimes).toString();
			temp[0] = "deadline";
		}
		case ("todo"): {
			todoDeleteTimes++;
			temp[1] = new Integer(todoDeleteTimes).toString();
			temp[0] = "todo";
		}
		}
		return temp;

	}

	private static StringBuilder findIndexForMultipleDeletion(
			String[] eachLine, int scheduleTimes, int deadlineTimes) {
		StringBuilder sb = new StringBuilder();
		int number = Integer.parseInt(eachLine[0]);
		sb = getIndex(eachLine, number, sb, "schedule", 0);
		sb = getIndex(eachLine, number, sb, "deadline", scheduleTimes);
		sb = getIndex(eachLine, number, sb, "todo", deadlineTimes
				+ scheduleTimes);
		return sb;
	}

	private static StringBuilder getIndex(String[] eachLine, int number,
			StringBuilder sb, String string, int times) {
		try {
			for (int i = 1; i <= number; i++) {
				if (findType(eachLine[i]).equals(string)) {
					sb.append((findLineNumber(eachLine[i]) + times) + " ");
				}
			}
		} catch (IndexOutOfBoundsException e) {
			LOGGER.log(Level.SEVERE, "number != eachLine.length!");
		}
		return sb;
	}

	private static String[][] appendEventList(Vector<Integer> listOfNumbers,
			String[][] listOfEvents, FileOperator scheduledFile, int index,
			String type) {
		try {
			for (Integer sequenceNo : listOfNumbers) {
				String[][] temp;
				temp = convertToTable(type,
						scheduledFile.getLineContent(sequenceNo), index);
				for (int i = 0; i < 3; i++) {
					listOfEvents[index - 1][i] = temp[0][i];
				}
				index++;
			}
		} catch (IndexOutOfBoundsException e) {
			LOGGER.log(Level.SEVERE, "format of events must be wrong!");
		}

		return listOfEvents;
	}

	private static String replaceInTodo(String originalString,
			String replacementString, String fieldKeyword, Event event) {

		switch (fieldKeyword) {
		case ("label"): {
			return replacementString + " Incomplete";
		}
		case ("status"): {
			try {
				return originalString.substring(0,
						originalString.lastIndexOf("I"))
						+ "Completed";
			} catch (Exception e) {
				return null;
			}
		}
		default: {
			LOGGER.log(Level.SEVERE, "Wrong fieldKeyword in todo tasks");
			return originalString;
		}
		}

	}

	private static String replaceInDeadline(String originalString,
			String replacementString, String fieldKeyword, Event event) {

		switch (fieldKeyword) {
		case ("label"): {
			lineContent = originalString.split("by");
			return replacementString + " by "
			+ lineContent[lineContent.length - 1];
		}
		case ("status"): {
			try {
				return originalString.substring(0,
						originalString.lastIndexOf("I"))
						+ "Completed";
			} catch (Exception e) {
				return null;
			}
		}
		case ("enddate"): {
			return replaceWithTime(0, 3, originalString, event.endDate, "by");
		}

		case ("endtime"): {
			return replaceWithTime(3, 1, originalString, event.endTime, "by");
		}
		default: {
			LOGGER.log(Level.SEVERE, "Wrong fieldKeyword in schedule tasks");
			return originalString;
		}
		}

	}

	private static String replaceInSchedule(String originalString,
			String replacementString, String fieldKeyword, Event event) {
		String temp = new String();

		switch (fieldKeyword) {
		case ("label"): {

			lineContent = originalString.split("from");

			return replacementString + " from "
			+ lineContent[lineContent.length - 1];
		}
		case ("status"): {
			try {
				return originalString.substring(0,
						originalString.lastIndexOf("I"))
						+ "Completed";
			} catch (Exception e) {
				return null;
			}
		}
		case ("startdate"): {
			return replaceWithTime(0, 3, originalString, event.startDate,
					"from");
		}
		case ("starttime"): {
			return replaceWithTime(3, 1, originalString, event.startTime,
					"from");
		}
		case ("enddate"): {
			return replaceWithTime(0, 3, originalString, event.endDate, "to");
		}
		case ("endtime"): {
			return replaceWithTime(3, 1, originalString, event.endTime, "to");

		}
		default: {
			LOGGER.log(Level.SEVERE, "Wrong type in replacement in schedule!");
		}
		}
		return temp;

	}

	public static String replaceWithTime(int indexNo, int length,
			String originalString, String replacementString, String splitKeyword) {
		int index = originalString.lastIndexOf(splitKeyword);
		String previousPart = originalString.substring(0, index);
		String lastpart = originalString.substring(index
				+ splitKeyword.length() + 1);
		lineContent = lastpart.split(" ");

		replacementContent = replacementString.split(" ");
		// replacementContent.length() should equals to length.

		assert replacementContent.length == length;
		if (replacementContent.length == length) {
			for (int j = indexNo; j < indexNo + length; j++) {
				lineContent[j] = replacementContent[j - indexNo];
			}
			lastpart = "";
			for (int i = 0; i < lineContent.length; i++) {
				lastpart = lastpart + " " + lineContent[i];
			}
		}
		return previousPart + splitKeyword + lastpart;
	}

	private static String[][] convertToTable(String type, String target,
			int sequenceNo) {
		String[][] temp = new String[1][3];
		String status, event = new String(), previousPart, start = new String(), end = new String();
		try {
			if (target.substring(target.length() - 10).equals("Incomplete")) {
				status = "Incomplete";
			} else {
				status = "Completed";

			}

			temp[0][0] = new Integer(sequenceNo).toString();
			if (status.equals("Completed")) {
				previousPart = target.substring(0, target.length() - 10);
			} else {
				previousPart = target.substring(0, target.length() - 11);
			}
			switch (type) {
			case ("todo"): {
				event = previousPart;
				start = null;
				end = null;

				break;
			}
			case ("deadline"): {
				int index = previousPart.lastIndexOf("by");
				end = previousPart.substring(index + 3);
				event = previousPart.substring(0, index - 1);
				start = null;

				break;
			}
			case ("schedule"): {
				int fromIndex = previousPart.lastIndexOf("from");
				int toIndex = previousPart.lastIndexOf("to");
				event = previousPart.substring(0, fromIndex - 1);
				start = previousPart.substring(fromIndex + 5, toIndex);
				end = previousPart.substring(toIndex + 3);

				break;
			}
			default: {
				LOGGER.log(Level.SEVERE, "Wrong type in converting to table!");
				return temp;
			}
			}
			temp[0][0] = temp[0][0] + ".  " + event;
			temp[0][1] = start;
			temp[0][2] = end;
		} catch (IndexOutOfBoundsException e) {
			LOGGER.log(Level.SEVERE,
					"Format of events must be wrong in converting to table!");
		}
		return temp;

	}

	public static String convertToStandard(String target, String type) {
		StringBuilder newString = new StringBuilder();
		String status, event, previousPart, start, end;
		if (target.substring(target.length() - 10).equals("Incomplete")) {
			status = "Incomplete";
		} else {
			status = "Completed";
		}
		if (status.equals("Completed")) {
			previousPart = target.substring(0, target.length() - 10);
		} else {
			previousPart = target.substring(0, target.length() - 11);
		}

		switch (type) {
		case ("todo"): {
			event = previousPart;

			newString.append("\n    Event label:       " + event
					+ "\n    Current status:  " + status);

			break;
		}
		case ("deadline"): {
			int index = previousPart.lastIndexOf("by");
			end = previousPart.substring(index + 3);
			event = previousPart.substring(0, index - 1);

			newString.append("\n    Event label:       " + event
					+ "\n    Deadline:          " + end
					+ "\n    Current status:  " + status);

			break;
		}
		case ("schedule"): {

			int fromIndex = previousPart.lastIndexOf("from");
			int toIndex = previousPart.lastIndexOf("to ");

			event = previousPart.substring(0, fromIndex - 1);

			start = previousPart.substring(fromIndex + 5, toIndex);
			end = previousPart.substring(toIndex + 3);

			newString.append("\n    Event label:       " + event
					+ "\n    Start from:        " + start
					+ "\n    End by:             " + end
					+ "\n    Current status:  " + status);

			break;
		}
		default: {
			LOGGER.log(Level.SEVERE, "Wrong type in converting to standard!");

		}
		}
		return newString.toString();
	}
}
